using System;

namespace Sustainalytics.Entities.ESGRatings
{
    public class ESGProfile : IEntity
    {
        public ESGProfile()
        {
        }

        public ESGProfile(Guid matrixId, Guid refereceUniverseId, Guid? accountId, ComparativeGroupEnum comparativeGroup, string name, string matrixName, string referenceUniverseName)
        {
            MatrixId = matrixId;

            ReferenceUniverseId = refereceUniverseId;
            AccountId = accountId;
            ComparativeGroup = comparativeGroup;
            Name = name;
            MatrixName = matrixName;
            ReferenceUniverseName = referenceUniverseName;
        }

        public ESGProfile(Guid matrixId, Guid refereceUniverseId, Guid? accountId, ComparativeGroupEnum comparativeGroup,
            string name, string matrixName, string referenceUniverseName, AccessLevel accountType,
            ActiveTypeEnum? activeStatus, Guid id, TemplateTypeEnum templateType, CompanyTypeEnum companyType)
        {
            Id = id;
            AccountId = accountId;
            AccountType = accountType;
            Active = activeStatus;
            Name = name;
            MatrixId = matrixId;
            MatrixName = matrixName;
            ReferenceUniverseId = refereceUniverseId;
            ReferenceUniverseName = referenceUniverseName;
            TemplateType = templateType;
            CompanyType = companyType;
            ComparativeGroup = comparativeGroup;
            LastModifiedDate = DateTime.UtcNow;
        }

        public Guid Id { get; set; }

        public Guid? AccountId { get; set; }

        public AccessLevel AccountType { get; set; }

        public ActiveTypeEnum? Active { get; set; }

        public string Name { get; set; }

        public Guid MatrixId { get; set; }
        public string MatrixName { get; set; }

        public Guid ReferenceUniverseId { get; set; }
        public string ReferenceUniverseName { get; set; }

        public DateTime LastModifiedDate { get; set; }

        public TemplateTypeEnum TemplateType { get; set; }
        public CompanyTypeEnum CompanyType { get; set; }
        public ComparativeGroupEnum ComparativeGroup { get; set; }

        protected bool Equals(ESGProfile other)
        {
            return Id.Equals(other.Id) &&
                Active == other.Active &&
                AccountId.Equals(other.AccountId)
                && MatrixId.Equals(other.MatrixId)
                && ReferenceUniverseId.Equals(other.ReferenceUniverseId)
                && TemplateType == other.TemplateType
                && CompanyType == other.CompanyType
                && ComparativeGroup == other.ComparativeGroup;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            return Equals((ESGProfile)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                var hashCode = Id.GetHashCode();
                hashCode = (hashCode * 397) ^ Active.GetHashCode();
                hashCode = (hashCode * 397) ^ AccountId.GetHashCode();
                hashCode = (hashCode * 397) ^ MatrixId.GetHashCode();
                hashCode = (hashCode * 397) ^ ReferenceUniverseId.GetHashCode();
                hashCode = (hashCode * 397) ^ (int)TemplateType;
                hashCode = (hashCode * 397) ^ (int)CompanyType;
                hashCode = (hashCode * 397) ^ (int)ComparativeGroup;
                return hashCode;
            }
        }

        public override string ToString()
        {
            return string.Format("[{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}|{10}|{11}|{12}]",
               Id, AccountId, AccountType, Active, Name, MatrixId, MatrixName, ReferenceUniverseId, ReferenceUniverseName, LastModifiedDate, TemplateType, CompanyType, ComparativeGroup
                );
        }

        #region Default profile implementation

        private static readonly ESGDefaultProfile _defaultProfile = new ESGDefaultProfile();

        public static ESGDefaultProfile DefaultProfile
        {
            get { return _defaultProfile; }
        }

        public class ESGDefaultProfile : ESGProfile
        {
            public ESGDefaultProfile()
                : base(Guid.Empty, Guid.Empty, null, ComparativeGroupEnum.PeerGroup, "Default", "Default Weight Matrix", "Default")
            {
                TemplateType = TemplateTypeEnum.Combined;
                CompanyType = CompanyTypeEnum.Combined;
                AccountType = AccessLevel.Tier3;
                Active = null;
            }

            public ESGDefaultProfile(Guid matrixId, Guid refereceUniverseId, Guid id)
                : base(matrixId, refereceUniverseId, null, ComparativeGroupEnum.PeerGroup, "Default", "Default Weight Matrix", "Default", AccessLevel.Tier3,
                       null, id, TemplateTypeEnum.Combined, CompanyTypeEnum.Combined)
            {
            }
        }

        #endregion
    }

    public enum TemplateTypeEnum
    {
        TypeA,
        TypeB,
        Combined
    }

    [Flags]
    public enum CompanyTypeEnum
    {
        Public = 1,
        Private = 2,
        Comprehensive = 4,
        Core = 8,
        Combined = 16
    }

    public enum ComparativeGroupEnum
    {
        PeerGroup,
        IndustryGroup
    }

    public enum ActiveTypeEnum
    {
        Active,
        NotActive,
        Suggested
    }
}

namespace Sustainalytics.Entities.ESGRatings.Historical
{
    public class ESGProfile : ESGRatings.ESGProfile
    {
        public DateTime ProcessedDate { get; set; }

        public ESGRatings.ESGProfile Instance { get; set; }

        public ESGProfile(ESGRatings.ESGProfile instance, DateTime processingDate)
        {
            Instance = instance;
            ProcessedDate = processingDate;
        }
    }
}
